package com.guozinhs.auto.log;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import com.guozinhs.auto.data.AgConstant;
import lombok.Data;

import javax.swing.*;
import java.awt.*;
import java.util.Map;
import java.util.Objects;

/**
 * 日志输出
 *
 * @Author: GuoZi
 * @Date: 2022/2/12 22:33
 */
@Data
public class Logger {

    private int maxLine = 100;
    private final Map<String, Component> componentMap;

    private static final String EMPTY_STR = "";
    private static final String EMPTY_STR_JSON = "{}";

    public Logger(Map<String, Component> componentMap) {
        this.componentMap = componentMap;
    }

    /**
     * 输出日志
     * <p>
     * 1. 默认会在内容开头加上换行符
     * 2. 日志内容可使用{}替换符, 具体规则同{@link cn.hutool.core.util.StrUtil#format(java.lang.CharSequence, java.lang.Object...)}
     *
     * @param log    日志内容
     * @param params 日志内容参数
     */
    public void info(String log, Object... params) {
        String content = StrUtil.format("\r\n[info] {} - {}", DateUtil.now(), this.format(log, params));
        this.consumeLog(content, null);
    }

    /**
     * 输出异常日志
     * <p>
     * 规则同上
     *
     * @param log 日志内容
     * @param e   异常信息
     */
    public void error(String log, Throwable e) {
        String content = StrUtil.format("\r\n[error]{} - {} : {}", DateUtil.now(), log, e.getMessage());
        this.consumeLog(content, e);
    }

    /**
     * 输出日志(不换行)
     *
     * @param log    日志内容
     * @param params 日志内容参数
     */
    public void appendInfo(String log, Object... params) {
        this.consumeLog(this.format(log, params), null);
    }

    /**
     * 处理日志输出
     *
     * @param log 日志内容
     * @param e   异常信息
     */
    private void consumeLog(String log, Throwable e) {
        JTextArea logArea = (JTextArea) this.componentMap.get(AgConstant.KEY_LOG_AREA);
        String originalText = logArea.getText();
        String[] subLog = originalText.split("\r\n");
        if (subLog.length >= this.maxLine) {
            originalText = originalText.substring(originalText.indexOf("\r\n") + 2);
        }
        // 输出日志到窗口
        logArea.setText(originalText + log);
        // 定位到日志底部
        logArea.setSelectionStart(logArea.getText().length());
        // 输出日志到文件
        if (Objects.nonNull(e)) {
            StackTraceElement[] stackTraces = e.getStackTrace();
            StringBuilder builder = new StringBuilder(log);
            for (StackTraceElement stackTrace : stackTraces) {
                builder.append("\r\n").append(stackTrace.toString());
            }
            log = builder.toString();
        }
        FileUtil.appendUtf8String(log, AgConstant.PATH_LOG_FILE);
    }

    /**
     * 字符串模板替换
     *
     * @param log    日志模板
     * @param params 替换参数
     * @return 替换后的日志文本
     */
    private String format(String log, Object... params) {
        if (StrUtil.isBlank(log)) {
            return EMPTY_STR;
        }
        if (log.contains(EMPTY_STR_JSON)) {
            return StrUtil.format(log, params);
        } else {
            return String.format(log, params);
        }
    }

}
